/* 
 * (C) 2013 Daniel Garcia <contacto {at} danigarcia.org>
 * 
 * http://danigarcia.org
 * 
 * This file is part of BlackList.
 * 
 * BlackList is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * BlackList is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with BlackList.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */
package org.danigarcia.android.blacklist.phone;

import java.lang.reflect.Method;

import org.danigarcia.android.blacklist.database.ConfigManager;
import org.danigarcia.android.blacklist.database.DataManager;
import org.danigarcia.android.blacklist.service.BlockingService;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.telephony.TelephonyManager;
import android.util.Log;

import com.android.internal.telephony.ITelephony;

public class IncomingCallReceiver extends BroadcastReceiver {

	private static final String TAG = IncomingCallReceiver.class.getName();
	public static final String PHONE_STATE = "android.intent.action.PHONE_STATE";
	private Context context;
	private DataManager dataManager;
	private TelephonyManager tManager;

	public IncomingCallReceiver() {
		super();
	}

	public IncomingCallReceiver(Context c, DataManager dm, TelephonyManager tm) {
		super();
		this.context = c;
		this.dataManager = dm;
		this.tManager = tm;
		//Log.d(TAG, "IncomingCallReceiver()");
	}

	@Override
	public void onReceive(Context context, Intent intent) 
	{
		Log.d(TAG, "onReceive()");
		// Get the intent extra info
		Bundle extras = intent.getExtras();
		if (extras != null) 
		{
			try 
			{
				// If the phone state changes
				if (intent.getAction().equals(PHONE_STATE)) 
				{
					Log.d(TAG, "onReceive(PHONE_STATE)");
					// We get the state of the phone
					String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
					logBundle(extras);
					
					Log.d(TAG, "state = " + state == null ? "null" : state);
					Log.d(TAG, "EXTRA_STATE_RINGING = " + TelephonyManager.EXTRA_STATE_RINGING);
					
					// We compare the state with EXTRA_STATE_RINGING
					if (TelephonyManager.EXTRA_STATE_RINGING.equals(state)) 
					{
						Log.d(TAG, "onReceive(EXTRA_STATE_RINGING)");
						// Extract the number
						String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
						
						// Delete special characters like whitespaces
						incomingNumber = incomingNumber.replaceAll("\\s+","");
						Log.d(TAG, "onReceive(PHONE): " + incomingNumber == null ? "" : incomingNumber);
						
						// Check if the number is on the database. If so, block it
						if (dataManager.exists(incomingNumber, true)) 
						{
							// Silence ringer
							// silence();

							// If pickup before hanging
							if (ConfigManager.getBoolean(ConfigManager.KEY_PICKUP))
							{
								pickUp();
								try { Thread.sleep(1000); } catch(InterruptedException e) {};
							}

							// Hang up the phone
							hangUp();

							// Register the missed call into database
							dataManager.insertCall(incomingNumber);

							// Update notification
							if (context instanceof BlockingService) 
							{
								if (ConfigManager.getBoolean(ConfigManager.KEY_SHOW_NOTIFICATIONS))
									((BlockingService) context).updateNotification(incomingNumber, true, false);
							}
						}
						//Log.d(TAG, "onReceive(RINGING): END");
					}
				}
			} catch (Exception e) {
				Log.e(TAG, "onReceive()", e);
			}
		}
	}

	private void hangUp() {

		Class<TelephonyManager> telephonyManagerClass = TelephonyManager.class;
		Method getITelephony = null;

		try {
			getITelephony = telephonyManagerClass.getDeclaredMethod(
					"getITelephony", (Class[]) null);
			getITelephony.setAccessible(true);
			ITelephony iTelephony = (ITelephony) getITelephony.invoke(tManager);
			iTelephony.endCall();
		} catch (Exception e) {
			Log.e(TAG, "hangUp()", e);
		}

	}

	private void pickUp() {
		Class<TelephonyManager> telephonyManagerClass = TelephonyManager.class;
		Method getITelephony = null;

		try {
			getITelephony = telephonyManagerClass.getDeclaredMethod(
					"getITelephony", (Class[]) null);
			getITelephony.setAccessible(true);
			ITelephony iTelephony = (ITelephony) getITelephony.invoke(tManager);
			iTelephony.answerRingingCall();
		} catch (Exception e) {
			Log.e(TAG, "pickUp()");
		}
	}
	
	private void logBundle(Bundle bundle)
	{
		for (String key : bundle.keySet()) {
		    Object value = bundle.get(key);
		    Log.d("  -->  ", String.format("%s %s (%s)", key, value.toString(), value.getClass().getName()));
		}
	}
	
	/*
	 * @Override public void onCallStateChanged(int state, String
	 * incomingNumber) {
	 * 
	 * Log.d("AUX", String.format("onCallStateChanged(%s, %s): LISTENER %s",
	 * state, incomingNumber, n));
	 * 
	 * }
	 */

	/*
	 * // Incoming call String incomingNumber =intent.getStringExtra
	 * (TelephonyManager.EXTRA_INCOMING_NUMBER); System.out.println
	 * ("--------------my number---------"+incomingNumber);
	 * 
	 * // this is main section of the code,. could also be use for particular
	 * number. // Get the boring old TelephonyManager. TelephonyManager
	 * telephonyManager = (TelephonyManager)
	 * context.getSystemService(Context.TELEPHONY_SERVICE); Class clazz =
	 * Class.forName(telephonyManager.getClass().getName()); Method method =
	 * clazz.getDeclaredMethod("getITelephony"); method.setAccessible(true);
	 * 
	 * ITelephony telephonyService = (ITelephony)
	 * method.invoke(telephonyManager); //Checking incoming call number
	 * System.out.println("NUMERO DETECTADO");
	 */

}
